﻿using System;

using System.Collections.Generic;
using System.Text;
using System.Drawing;
using Silvermoon.Visuals;

using Silvermoon.Controls.Base;
using Silvermoon.Utils;
using Silvermoon.Images;
using Silvermoon.OpenGL;
using Silvermoon.Controls.Interfaces;

namespace Silvermoon.Controls
{
    /// <summary>
    /// Provides a standard button, optionally with toggle mode.
    /// </summary>
    public class Button : ButtonBase, IContextMenuBehavior
    {
        public const int ButtonCornerRadius = 18;
        #region Fields

        private BackgroundVisual background;
        private StringVisual visualText;
        private Color color;
        private bool shadowedText;

        #endregion
        #region ctor

        public Button()
            : base()
        {
            background = new BackgroundVisual();
            background.Texture = SysImages.Button;
            visualText = new StringVisual();
            Alpha = 255;
            Visuals = new Visual[] { background, visualText };
            TextColor = SysColors.ButtonTextColor;
            Color = SysColors.ButtonColor;

        }

        #endregion
        #region Props

        public FontSprite Font { get { return visualText.Font; } set { if (Font != value) { visualText.Font = value; Invalidate(InvalidationFlag.Appearance); } } }

        public string Text { get { return visualText.Text; } set { visualText.Text = value; OnTextChanged(); } }

        /// <summary>
        /// Gets or sets the style how to render the button.
        /// </summary>
        public RenderStyle Style
        {
            get { return background.Style; }
            set { if (Style != value) { background.Style = value; Invalidate(InvalidationFlag.Color); } }
        }

        /// <summary>
        /// Gets or sets whether the text has a shadow.
        /// </summary>
        public bool ShadowedText
        {
            get { return shadowedText; }
            set { if (shadowedText != value) { shadowedText = value; Invalidate(InvalidationFlag.Appearance); } }
        }

        /// <summary>
        /// Gets or sets the texture used to render the button.
        /// </summary>
        public Texture Texture
        {
            get { return background.Texture; }
            set
            {
                if (background.Texture != value)
                {
                    background.Texture = value;
                    Invalidate(InvalidationFlag.Texture);
                }
            }
        }

        public Color Color
        {
            get { return color; }
            set
            {
                if (color != value)
                {
                    color = value;
                    Invalidate(InvalidationFlag.Color);
                }
            }
        }


        #endregion
        #region Methods

        private static readonly Transformation[] flipTransformation = new Transformation[] { new RotateTransform { Angle = RotateTransform.Degree180, Axis = RotateAxis.XAxis } };

        protected virtual void SetBgColor()
        {
            Color color = this.color; // Enabled ? this.color : Color.SlateGray;
            background.Colors = Style == RenderStyle.Plastic ? ColorUtil.CreatePlasticColors(color) : ColorUtil.CreateChromeColors(color);
            background.Transformations = IsDownOrPressed && Enabled ? flipTransformation : null;
            background.Invalidate();
        }


        protected override void OnPressedChanged()
        {
            SetBgColor();
            base.OnPressedChanged();
        }

        protected virtual void OnTextChanged()
        {
            if (TextChanged != null) TextChanged(this, EventArgs.Empty);
            Invalidate(InvalidationFlag.Text);
        }

        protected override void OnLayout()
        {
            visualText.Shadowed = shadowedText;
            if (CheckFlag(InvalidationFlag.Color | InvalidationFlag.Enabled | InvalidationFlag.LayoutAppearance)) SetBgColor();
            visualText.Size = Control.ScaledSize(Width - 12, Height - 4);
            background.Size = Control.Scale(Size);
            visualText.Visible = !string.IsNullOrEmpty(Text);           
            visualText.Color = Enabled ?TextColor : ColorUtil.AlphaBlendColor(color, SysColors.ButtonTextColor, 128);

            Size textSize = Unscale(visualText.TextSize);
            int d = IsDownOrPressed ? Control.Scale(2) : 0;
            visualText.Location = ScaledPoint((Size.Width - textSize.Width) / 2 + d, (Size.Height - textSize.Height) / 2 + d);
        }

        public override void PreLoad()
        {
            visualText.PreLoad();
            base.PreLoad();
        }

        #endregion
        #region IContextMenu Members

        public ContextMenu ContextMenu { get; set; }

        #endregion
        #region events

        /// <summary>
        /// Occcurs when the text changes;
        /// </summary>
        public event EventHandler TextChanged;
        #endregion
    }
}
